Reading libraries and parameters

library(tidyverse)
library(quickpsy)
library(cowplot)
list.files("R", full.names = TRUE) %>% walk(source)
source("graphical_parameters.R")
source("parameters.R")
load(file = "logdata/dat2.RData")

No two guess

fun_sym_no_two_guess2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[5] + + (1 - p[5] - p[6]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[7] + (1 - p[7] - p[8]) * pnorm(x, p[1] - p[2], p[4]))))

fit_sym_no_two_guess2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_no_two_guess2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")

ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_no_two_guess2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_no_two_guess2$curves, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

Two guess

fun_sym_two_guess2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[5] + p[7] + (1 - 2 * p[5] - p[7]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[6] + (1 - 2 * p[6] - p[7]) * pnorm(x, p[1] - p[2], p[4]))))
fit_sym_two_guess2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_two_guess2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_two_guess2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_two_guess2$curves, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

No two guess vs two guess

sym_no_two_guess_vs_two_guess2 <- model_selection_lrt(
  fit_sym_no_two_guess2$logliks, 
  fit_sym_two_guess2$logliks) 
sym_no_two_guess_vs_two_guess2 %>% 
  group_by(best) %>% 
  count()
best_sym_no_two_guess2 <- sym_no_two_guess_vs_two_guess2 %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
best_sym_two_guess2 <- sym_no_two_guess_vs_two_guess2 %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)

No two guess same slope

fun_sym_no_two_guess_same_slope2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[4] + + (1 - p[4] - p[5]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[6] + (1 - p[6] - p[7]) * pnorm(x, p[1] - p[2], p[3]))))
fit_sym_no_two_guess_same_slope2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_no_two_guess_same_slope2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")

No two guess vs no two guess same slope

sym_no_two_guess_vs_no_two_guess_same_slope2 <- model_selection_lrt(
  fit_sym_no_two_guess2$logliks, 
  fit_sym_no_two_guess_same_slope2$logliks) 
sym_no_two_guess_vs_no_two_guess_same_slope2 %>%
  semi_join(best_sym_no_two_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_two_guess_same_slope2 <- sym_no_two_guess_vs_no_two_guess_same_slope2 %>% 
  semi_join(best_sym_no_two_guess2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")

Sym guess

fun_sym_guess2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[5] + (1 - 2 * p[5]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[6] + (1 - 2 * p[6]) * pnorm(x, p[1] - p[2], p[4]))))
fit_sym_guess2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_guess2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, pini_scale, 
                              pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_guess2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_guess2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Sym guess vs no sym guess

sym_two_guess_vs_sym_guess2 <- model_selection_lrt(
  fit_sym_two_guess2$logliks, 
  fit_sym_guess2$logliks) 
sym_two_guess_vs_sym_guess2 %>%
  semi_join(best_sym_two_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_guess2 <- best_sym_two_guess2

Sym same guess

fun_sym_same_guess2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[5] + (1 - 2 * p[5]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[5] + (1 - 2 * p[5]) * pnorm(x, p[1] - p[2], p[4]))))
fit_sym_same_guess2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject,  references, cond_per_block),
                fun = fun_sym_same_guess2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess vs no same slope

sym_same_guess_vs_no_same_guess2 <- model_selection_lrt(
  fit_sym_guess2$logliks, 
  fit_sym_same_guess2$logliks) 
sym_same_guess_vs_no_same_guess2 %>%
  semi_join(best_sym_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_no_same_guess2 <- sym_same_guess_vs_no_same_guess2 %>% 
  semi_join(best_sym_guess2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
best_sym_same_guess2 <- sym_same_guess_vs_no_same_guess2 %>% 
  semi_join(best_sym_guess2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")

No same guess same slope

fun_sym_guess_same_slope2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[5] + (1 - 2 * p[5]) * pnorm(x, p[1] - p[2], p[3]))))
fit_sym_guess_same_slope2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_guess_same_slope2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, 
                              pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_guess_same_slope2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_guess_same_slope2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

No same guess vs no same guess same slope

sym_same_guess_vs_same_guess_same_slope2 <- model_selection_lrt(
  fit_sym_guess2$logliks, 
  fit_sym_guess_same_slope2$logliks) 
sym_same_guess_vs_same_guess_same_slope2 %>%
  semi_join(best_sym_no_same_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_same_guess_same_slope2 <- best_sym_no_same_guess2
  

Absent lapses

fun_sym_absent_lapses2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1] - p[2], p[4]))))
fit_sym_absent_lapses2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses vs no absent lapses

sym_absent_lapses_vs_no_absent_lapses2 <- model_selection_lrt(
  fit_sym_same_guess2$logliks, 
  fit_sym_absent_lapses2$logliks) 
sym_absent_lapses_vs_no_absent_lapses2 %>%
  semi_join(best_sym_same_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_no_absent_lapses2 <- sym_absent_lapses_vs_no_absent_lapses2 %>% 
  semi_join(best_sym_same_guess2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
best_sym_absent_lapses2 <- sym_absent_lapses_vs_no_absent_lapses2 %>% 
  semi_join(best_sym_same_guess2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")

Sym same guess same slope

fun_sym_same_guess_same_slope2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1] - p[2], p[3]))))
fit_sym_same_guess_same_slope2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_same_slope2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_same_slope2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_same_slope2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

No absent lapses vs no absent lapses same slope

sym_no_absent_lapses_vs_no_absent_lapses_same_slope2 <- model_selection_lrt(
  fit_sym_same_guess2$logliks, 
  fit_sym_same_guess_same_slope2$logliks) 
sym_no_absent_lapses_vs_no_absent_lapses_same_slope2 %>%
  semi_join(best_sym_no_absent_lapses2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_absent_lapses_no_same_slope2 <- sym_no_absent_lapses_vs_no_absent_lapses_same_slope2 %>% 
  semi_join(best_sym_no_absent_lapses2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_absent_lapses_same_slope2 <- sym_no_absent_lapses_vs_no_absent_lapses_same_slope2 %>% 
  semi_join(best_sym_no_absent_lapses2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")

Absent lapses same slope

fun_sym_absent_lapses_same_slope2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1] + p[2], p[3]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1] - p[2], p[3]))))
fit_sym_absent_lapses_same_slope2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_same_slope2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_origin, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_same_slope2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_same_slope2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses vs absent lapses same slope

sym_absent_lapses_vs_absent_lapses_same_slope2 <- model_selection_lrt(
  fit_sym_absent_lapses2$logliks, 
  fit_sym_absent_lapses_same_slope2$logliks) 
sym_absent_lapses_vs_absent_lapses_same_slope2 %>%
  semi_join(best_sym_absent_lapses2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_absent_lapses_no_same_slope2 <- sym_absent_lapses_vs_absent_lapses_same_slope2 %>% 
  semi_join(best_sym_absent_lapses2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_absent_lapses_same_slope2 <- sym_absent_lapses_vs_absent_lapses_same_slope2 %>% 
  semi_join(best_sym_absent_lapses2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")

Averages, curves and parameters (checking)

sym_averages_s_vs_d_test2 <- 
  (fit_sym_no_two_guess_same_slope2$averages %>% semi_join(best_sym_no_two_guess_same_slope2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_no_two_guess_same_slope2$curves %>% semi_join(best_sym_no_two_guess_same_slope2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

sym_averages_s_vs_d_test2 <- 
  (fit_sym_guess_same_slope2$averages %>% semi_join(best_sym_no_same_guess2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_guess_same_slope2$curves %>% semi_join(best_sym_no_same_guess2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

sym_averages_s_vs_d_test2 <- 
  (fit_sym_same_guess2$averages %>% semi_join(best_sym_no_absent_lapses_no_same_slope2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_same_guess2$curves %>% semi_join(best_sym_no_absent_lapses_no_same_slope2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

sym_averages_s_vs_d_test2 <- 
  (fit_sym_same_guess_same_slope2$averages %>% semi_join(best_sym_no_absent_lapses_same_slope2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_same_guess_same_slope2$curves %>% semi_join(best_sym_no_absent_lapses_same_slope2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

sym_averages_s_vs_d_test2 <- 
  (fit_sym_absent_lapses2$averages %>% semi_join(best_sym_absent_lapses_no_same_slope2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_absent_lapses2$curves %>% semi_join(best_sym_absent_lapses_no_same_slope2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

sym_averages_s_vs_d_test2 <- 
  (fit_sym_absent_lapses_same_slope2$averages %>% semi_join(best_sym_absent_lapses_same_slope2))
Joining, by = c("subject", "cond_per_block")
sym_curves_s_vs_d_test2 <- 
  (fit_sym_absent_lapses_same_slope2$curves %>% semi_join(best_sym_absent_lapses_same_slope2))
Joining, by = c("subject", "cond_per_block")
ggplot() + facet_wrap(subject ~ cond_per_block) +
  geom_point(data = sym_averages_s_vs_d_test2, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = sym_curves_s_vs_d_test2, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

Averages, curves and parameters

No two guess same slope zero

fun_sym_no_two_guess_same_slope_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[2] + + (1 - p[2] - p[3]) * pnorm(x, 0, p[1]), 
    function(x, p) p[4] + (1 - p[4] - p[5]) * pnorm(x, 0, p[1]))))
fit_sym_no_two_guess_same_slope_zero2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_no_two_guess_same_slope_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_no_two_guess_same_slope_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_no_two_guess_same_slope_zero2$curves, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

No two guess same slope zero vs no two guess same slope

sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_zero2 <- model_selection_lrt(
  fit_sym_no_two_guess_same_slope2$logliks, 
  fit_sym_no_two_guess_same_slope_zero2$logliks) 
sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_zero2 %>%
  semi_join(best_sym_no_two_guess_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_no_two_guess_same_slope_no_zero2 <- sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_zero2 %>% 
  semi_join(best_sym_no_two_guess_same_slope2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_two_guess_same_slope_zero2 <- sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_zero2 %>% 
  semi_join(best_sym_no_two_guess_same_slope2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "zero")
Joining, by = c("subject", "cond_per_block")

No two guess same slope s

fun_sym_no_two_guess_same_slope_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + + (1 - p[3] - p[4]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[5] + (1 - p[5] - p[6]) * pnorm(x, p[1], p[2]))))
fit_sym_no_two_guess_same_slope_s2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_no_two_guess_same_slope_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_no_two_guess_same_slope_s2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_no_two_guess_same_slope_s2$curves, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

No two guess same slope vs no two guess same slope s

sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_s2 <- model_selection_lrt(
  fit_sym_no_two_guess_same_slope2$logliks, 
  fit_sym_no_two_guess_same_slope_s2$logliks) 
sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_s2 %>%
  semi_join(best_sym_no_two_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")

No two guess same slope d

fun_sym_no_two_guess_same_slope_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + + (1 - p[3] - p[4]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[5] + (1 - p[5] - p[6]) * pnorm(x, -p[1], p[2]))))
fit_sym_no_two_guess_same_slope_d2 <- quickpsy(dat2, orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_no_two_guess_same_slope_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse, pini_lapse, pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_no_two_guess_same_slope_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_no_two_guess_same_slope_d2$curves, 
            aes(x = x, y = y, color = references)) +
  theme_grey() + theme(legend.position = "top") 

No two guess same slope vs no two guess same slope d

sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_d2 <- model_selection_lrt(
  fit_sym_no_two_guess_same_slope2$logliks, 
  fit_sym_no_two_guess_same_slope_d2$logliks) 
sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_d2 %>%
  semi_join(best_sym_no_two_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_no_two_guess_same_slope_no_zero_full2 <- sym_no_two_guess_same_slope_vs_no_two_guess_same_slope_d2 %>% 
  semi_join(best_sym_no_two_guess_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "full")
Joining, by = c("subject", "cond_per_block")

No same guess same slope zero

fun_sym_guess_same_slope_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[2] + (1 - 2 * p[2]) * pnorm(x, 0, p[1]), 
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, 0, p[1]))))
fit_sym_guess_same_slope_zero2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_guess_same_slope_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale, 
                              pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_guess_same_slope_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_guess_same_slope_zero2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

No same guess same slope vs no same guess same slope zero

sym_guess_same_slope_vs_sym_guess_same_slope_zero2 <- model_selection_lrt(
  fit_sym_guess_same_slope2$logliks, 
  fit_sym_guess_same_slope_zero2$logliks) 
sym_guess_same_slope_vs_sym_guess_same_slope_zero2 %>%
  semi_join(best_sym_no_same_guess2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_guess_same_slope_no_zero2 <- sym_guess_same_slope_vs_sym_guess_same_slope_zero2 %>% 
  semi_join(best_sym_no_same_guess2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")

No same guess same slope s

fun_sym_guess_same_slope_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1], p[2]))))
fit_sym_guess_same_slope_s2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_guess_same_slope_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse, pini_lapse),
                bootstrap = "none")

No same guess same slope no zero vs no same guess same slope no zero s

sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_s2 <- model_selection_lrt(
  fit_sym_guess_same_slope2$logliks, 
  fit_sym_guess_same_slope_s2$logliks) 
sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_s2 %>%
  semi_join(best_sym_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_guess_same_slope_no_zero_no_s2 <- sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_guess_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")
best_sym_guess_same_slope_no_zero_s2 <- sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_guess_same_slope_no_zero2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")

No same guess same slope d

fun_sym_guess_same_slope_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, -p[1], p[2]))))
fit_sym_guess_same_slope_d2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_guess_same_slope_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse, pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_guess_same_slope_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_guess_same_slope_d2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

No same guess same slope no zero vs no same guess same slope no zero d

sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_d2 <- model_selection_lrt(
  fit_sym_guess_same_slope2$logliks, 
  fit_sym_guess_same_slope_d2$logliks) 
sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_d2 %>%
  semi_join(best_sym_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_guess_same_slope_no_zero_full2 <- sym_guess_same_slope_no_zero_vs_guess_same_slope_no_zero_d2 %>% 
  semi_join(best_sym_guess_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "full")
Joining, by = c("subject", "cond_per_block")

Sym same guess no same slope zero

fun_sym_same_guess_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, 0, p[1]), 
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, 0, p[2]))))
fit_sym_same_guess_zero2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_zero2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess no same slope no zero vs Same guess no same slope zero

sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_zero2 <- model_selection_lrt(
  fit_sym_same_guess2$logliks, 
  fit_sym_same_guess_zero2$logliks) 
sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_zero2 %>%
  semi_join(best_sym_no_absent_lapses_no_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_same_guess_no_same_slope_no_zero <- sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_zero2 %>% 
  semi_join(best_sym_no_absent_lapses_no_same_slope2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_same_guess_no_same_slope_zero2 <- sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_zero2 %>% 
  semi_join(best_sym_no_absent_lapses_no_same_slope2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "zero")
Joining, by = c("subject", "cond_per_block")

Sym same guess no same slope no zero s

fun_sym_same_guess_no_zero_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1], p[3]))))
fit_sym_same_guess_no_zero_s2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_no_zero_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_no_zero_s2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_no_zero_s2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess no same slope no zero vs Same guess no same slope no zero s

sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_no_zero_s2 <- model_selection_lrt(
  fit_sym_same_guess2$logliks, 
  fit_sym_same_guess_no_zero_s2$logliks) 
sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_no_zero_s2 %>%
  semi_join(best_sym_same_guess_no_same_slope_no_zero) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")

Sym same guess no same slope no zero d

fun_sym_same_guess_no_zero_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[4] + (1 - 2 * p[4]) * pnorm(x, -p[1], p[3]))))
fit_sym_same_guess_no_zero_d2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_no_zero_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_no_zero_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_no_zero_d2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess no same slope no zero vs Same guess no same slope no zero d

sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_no_zero_d2 <- model_selection_lrt(
  fit_sym_same_guess2$logliks, 
  fit_sym_same_guess_no_zero_d2$logliks) 
sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_no_zero_d2%>%
  semi_join(best_sym_same_guess_no_same_slope_no_zero) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_same_guess_no_same_slope_no_zero_s2 <- sym_same_guess_no_same_slope_no_zero_vs_same_guess_no_same_slope_no_zero_d2 %>% 
  semi_join(best_sym_same_guess_no_same_slope_no_zero) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>%  
  mutate(best = "sensory")
Joining, by = c("subject", "cond_per_block")

Sym same guess same slope zero

fun_sym_same_guess_same_slope_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[2] + (1 - 2 * p[2]) * pnorm(x, 0, p[1]), 
    function(x, p) p[2] + (1 - 2 * p[2]) * pnorm(x, 0, p[1]))))
fit_sym_same_guess_same_slope_zero2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_same_slope_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_same_slope_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_same_slope_zero2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess same slope no zero vs same guess same slope zero

sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_zero2 <- model_selection_lrt(
  fit_sym_same_guess_same_slope2$logliks, 
  fit_sym_same_guess_same_slope_zero2$logliks) 
sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_zero2 %>%
  semi_join(best_sym_no_absent_lapses_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_same_guess_same_slope_no_zero2 <- sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_zero2 %>% 
  semi_join(best_sym_no_absent_lapses_same_slope2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")

Sym same guess same slope no zero s

fun_sym_same_guess_same_slope_no_zero_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, p[1], p[2]))))
fit_sym_same_guess_same_slope_no_zero_s2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_same_slope_no_zero_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_same_slope_no_zero_s2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_same_slope_no_zero_s2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess same slope no zero vs same guess same slope no zero s

sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_s2 <- model_selection_lrt(
  fit_sym_same_guess_same_slope2$logliks, 
  fit_sym_same_guess_same_slope_no_zero_s2$logliks) 
sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_s2 %>%
  semi_join(best_sym_same_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")

Sym same guess same slope no zero d

fun_sym_same_guess_same_slope_no_zero_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, p[1], p[2]), 
    function(x, p) p[3] + (1 - 2 * p[3]) * pnorm(x, -p[1], p[2]))))
fit_sym_same_guess_same_slope_no_zero_d2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_same_guess_same_slope_no_zero_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, 
                              pini_lapse),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_same_guess_same_slope_no_zero_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_same_guess_same_slope_no_zero_d2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Same guess same slope no zero vs same guess same slope no zero d

sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_d2 <- model_selection_lrt(
  fit_sym_same_guess_same_slope2$logliks, 
  fit_sym_same_guess_same_slope_no_zero_d2$logliks) 
sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_d2 %>%
  semi_join(best_sym_same_guess_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_same_guess_same_slope_no_zero_full2 <- sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_same_guess_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "full")
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_same_guess_same_slope_no_zero_s2 <- sym_same_guess_same_slope_no_zero_vs_same_guess_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_same_guess_same_slope_no_zero2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "sensory")
Joining, by = c("subject", "cond_per_block")

Absent lapses no same slope zero

fun_sym_absent_lapses_no_same_slope_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, 0, p[1]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, 0, p[2]))))
fit_sym_absent_lapses_no_same_slope_zero2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_no_same_slope_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_no_same_slope_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_no_same_slope_zero2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses no same slope vs absent lapses no same slope zero

sym_absent_lapses_no_same_slope_vs_absent_lapses_no_same_slope_zero2 <- model_selection_lrt(
  fit_sym_absent_lapses2$logliks, 
  fit_sym_absent_lapses_no_same_slope_zero2$logliks) 
sym_absent_lapses_no_same_slope_vs_absent_lapses_no_same_slope_zero2 %>%
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")

Absent lapses no same slope no zero s

fun_sym_absent_lapses_no_same_slope_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[2]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[3]))))
fit_sym_absent_lapses_no_same_slope_s2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_no_same_slope_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_no_same_slope_s2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_no_same_slope_s2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses no same slope no zero vs absent lapses no same slope no zero s

sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_s2 <- model_selection_lrt(
  fit_sym_absent_lapses2$logliks, 
  fit_sym_absent_lapses_no_same_slope_s2$logliks) 
sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_s2 %>%
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_sym_absent_lapses_no_same_slope_no_zero_no_s2 <- sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_absent_lapses_no_same_slope_no_zero_s2 <- sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_s2 %>% 
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "sensory")
Joining, by = c("subject", "cond_per_block")

Absent lapses no same slope no zero d

fun_sym_absent_lapses_no_same_slope_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[2]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, -p[1], p[3]))))
fit_sym_absent_lapses_no_same_slope_d2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_no_same_slope_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_no_same_slope_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_no_same_slope_d2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses no same slope no zero vs absent lapses no same slope no zero d

sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_d2 <- model_selection_lrt(
  fit_sym_absent_lapses2$logliks, 
  fit_sym_absent_lapses_no_same_slope_d2$logliks) 
sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_d2 %>%
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_absent_lapses_no_same_slope_no_zero_full2 <- sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_d2 %>% 
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  anti_join(best_sym_absent_lapses_no_same_slope_no_zero_s2, by = c("subject", "cond_per_block")) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "full")
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_sym_absent_lapses_no_same_slope_no_zero_d2 <- sym_absent_lapses_no_same_slope_no_zero_vs_absent_lapses_no_same_slope_no_zero_d2 %>% 
  semi_join(best_sym_absent_lapses_no_same_slope2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "decision")
Joining, by = c("subject", "cond_per_block")

Absent lapses same slope zero

fun_sym_absent_lapses_same_slope_zero2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, 0, p[1]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, 0, p[1]))))
fit_sym_absent_lapses_same_slope_zero2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_same_slope_zero2,
                xmin = -3, xmax = 3,
                parini = list(pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_same_slope_zero2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_same_slope_zero2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses same slope no zero vs absent lapses same slope zero

sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_zero2 <- model_selection_lrt(
  fit_sym_absent_lapses_same_slope2$logliks, 
  fit_sym_absent_lapses_same_slope_zero2$logliks) 
sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_zero2 %>%
  semi_join(best_sym_absent_lapses_same_slope2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_absent_lapses_same_slope_no_zero2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_zero2 %>% 
  semi_join(best_sym_absent_lapses_same_slope2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block)
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_absent_lapses_same_slope_zero2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_zero2 %>% 
  semi_join(best_sym_absent_lapses_same_slope2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "zero")
Joining, by = c("subject", "cond_per_block")

Absent lapses same slope no zero s

fun_sym_absent_lapses_same_slope_no_zero_s2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[2]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[2]))))
fit_sym_absent_lapses_same_slope_no_zero_s2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_same_slope_no_zero_s2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_same_slope_no_zero_s2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_same_slope_no_zero_s2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses same slope no zero vs absent lapses same slope no zero s

sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 <- model_selection_lrt(
  fit_sym_absent_lapses_same_slope2$logliks, 
  fit_sym_absent_lapses_same_slope_no_zero_s2$logliks) 
sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 %>%
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
best_absent_lapses_same_slope_no_zero_no_s2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 %>% 
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")
best_absent_lapses_same_slope_no_zero_s2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 %>% 
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) 
Joining, by = c("subject", "cond_per_block")

Absent lapses same slope no zero d

fun_sym_absent_lapses_same_slope_no_zero_d2 <-  dat2 %>% 
  distinct(references) %>% 
  bind_cols(tibble(fun = c(
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, p[1], p[2]), 
    function(x, p) 0.01 + (1 - 2 * 0.01) * pnorm(x, -p[1], p[2]))))
fit_sym_absent_lapses_same_slope_no_zero_d2 <- quickpsy(dat2, 
                               orientation, response, 
                grouping = .(subject, references, cond_per_block),
                fun = fun_sym_absent_lapses_same_slope_no_zero_d2,
                xmin = -3, xmax = 3,
                parini = list(pini_origin, pini_scale),
                bootstrap = "none")
ggplot() + facet_wrap(subject ~ cond_per_block, ncol = 6) +
  geom_point(data = fit_sym_absent_lapses_same_slope_no_zero_d2$averages, 
             aes(x = orientation, y = prob, color = references)) +
  geom_line(data = fit_sym_absent_lapses_same_slope_no_zero_d2$curves, 
            aes(x = x, y = y, color = references, lty = "all")) +
  theme_grey() + theme(legend.position = "top") 

Absent lapses same slope no zero vs absent lapses same slope no zero d

sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_d2 <- model_selection_lrt(
  fit_sym_absent_lapses_same_slope2$logliks, 
  fit_sym_absent_lapses_same_slope_no_zero_d2$logliks) 
sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_d2 %>%
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  group_by(best) %>% 
  count()
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_absent_lapses_same_slope_no_zero_no_s2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 %>% 
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  filter(best == "first") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "full")
Joining, by = c("subject", "cond_per_block")
### Add to s vs d
best_absent_lapses_same_slope_no_zero_s2 <- sym_absent_lapses_same_slope_no_zero_vs_absent_lapses_same_slope_no_zero_s2 %>% 
  semi_join(best_absent_lapses_same_slope_no_zero2) %>% 
  filter(best == "second") %>% 
  select(subject, cond_per_block) %>% 
  mutate(best = "sensory")
Joining, by = c("subject", "cond_per_block")

Add all best

sym_curves_s_vs_d_best2 <- sym_curves_s_vs_d2 %>% 
  left_join(best2)
Joining, by = c("subject", "cond_per_block")
sym_par_s_vs_d_best2 <- sym_par_s_vs_d2 %>% 
  left_join(best2) 
Joining, by = c("subject", "cond_per_block")

Save data

save(sym_averages_s_vs_d_best, file = "logdata/sym_averages_s_vs_d_best2.Rdata")
save(sym_curves_s_vs_d_best, file = "logdata/sym_curves_s_vs_d_best2.RData")
save(sym_par_s_vs_d_best, file = "logdata/sym_par_s_vs_d_best_long2.RData")
save(sym_par_s_vs_d_best_long, file = "logdata/sym_par_s_vs_d_best_abs2.RData")
LS0tCnRpdGxlOiAiU3ltbWV0cmljIHRhc2sgIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyMgUmVhZGluZyBsaWJyYXJpZXMgYW5kIHBhcmFtZXRlcnMKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShxdWlja3BzeSkKbGlicmFyeShjb3dwbG90KQoKbGlzdC5maWxlcygiUiIsIGZ1bGwubmFtZXMgPSBUUlVFKSAlPiUgd2Fsayhzb3VyY2UpCnNvdXJjZSgiZ3JhcGhpY2FsX3BhcmFtZXRlcnMuUiIpCnNvdXJjZSgicGFyYW1ldGVycy5SIikKCmxvYWQoZmlsZSA9ICJsb2dkYXRhL2RhdDIuUkRhdGEiKQoKYGBgCgojIyMgTm8gdHdvIGd1ZXNzICAKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLnN3aWR0aD0xNX0KZnVuX3N5bV9ub190d29fZ3Vlc3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFs1XSArICsgKDEgLSBwWzVdIC0gcFs2XSkgKiBwbm9ybSh4LCBwWzFdICsgcFsyXSwgcFszXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFs3XSArICgxIC0gcFs3XSAtIHBbOF0pICogcG5vcm0oeCwgcFsxXSAtIHBbMl0sIHBbNF0pKSkpCgpmaXRfc3ltX25vX3R3b19ndWVzczIgPC0gcXVpY2twc3koZGF0Miwgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX25vX3R3b19ndWVzczIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9vcmlnaW4sIHBpbmlfc2NhbGUsIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9ub190d29fZ3Vlc3MyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX25vX3R3b19ndWVzczIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgVHdvIGd1ZXNzCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV90d29fZ3Vlc3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFs1XSArIHBbN10gKyAoMSAtIDIgKiBwWzVdIC0gcFs3XSkgKiBwbm9ybSh4LCBwWzFdICsgcFsyXSwgcFszXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFs2XSArICgxIC0gMiAqIHBbNl0gLSBwWzddKSAqIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzRdKSkpKQoKZml0X3N5bV90d29fZ3Vlc3MyIDwtIHF1aWNrcHN5KGRhdDIsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgCiAgICAgICAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlcywgY29uZF9wZXJfYmxvY2spLAogICAgICAgICAgICAgICAgZnVuID0gZnVuX3N5bV90d29fZ3Vlc3MyLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW4sIHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSwgcGluaV9sYXBzZSwgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fdHdvX2d1ZXNzMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV90d29fZ3Vlc3MyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIE5vIHR3byBndWVzcyB2cyB0d28gZ3Vlc3MKYGBge3J9CnN5bV9ub190d29fZ3Vlc3NfdnNfdHdvX2d1ZXNzMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fbm9fdHdvX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX3R3b19ndWVzczIkbG9nbGlrcykgCgpzeW1fbm9fdHdvX2d1ZXNzX3ZzX3R3b19ndWVzczIgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgpiZXN0X3N5bV9ub190d29fZ3Vlc3MyIDwtIHN5bV9ub190d29fZ3Vlc3NfdnNfdHdvX2d1ZXNzMiAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCmJlc3Rfc3ltX3R3b19ndWVzczIgPC0gc3ltX25vX3R3b19ndWVzc192c190d29fZ3Vlc3MyICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCmBgYAoKIyMjIE5vIHR3byBndWVzcyBzYW1lIHNsb3BlICAKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpmdW5fc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbNF0gKyArICgxIC0gcFs0XSAtIHBbNV0pICogcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbM10pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbNl0gKyAoMSAtIHBbNl0gLSBwWzddKSAqIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSkpKQoKZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIgPC0gcXVpY2twc3koZGF0Miwgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX29yaWdpbiwgcGluaV9zY2FsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UpLAogICAgICAgICAgICAgICAgYm9vdHN0cmFwID0gIm5vbmUiKQoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgTm8gdHdvIGd1ZXNzIHZzIG5vIHR3byBndWVzcyBzYW1lIHNsb3BlCmBgYHtyfQpzeW1fbm9fdHdvX2d1ZXNzX3ZzX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fbm9fdHdvX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiRsb2dsaWtzKSAKCnN5bV9ub190d29fZ3Vlc3NfdnNfbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3MyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIgPC0gc3ltX25vX3R3b19ndWVzc192c19ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3MyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gInNlY29uZCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spCgpgYGAKCiMjIyBTeW0gZ3Vlc3MKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpmdW5fc3ltX2d1ZXNzMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbNV0gKyAoMSAtIDIgKiBwWzVdKSAqIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKSwgCiAgICBmdW5jdGlvbih4LCBwKSBwWzZdICsgKDEgLSAyICogcFs2XSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFs0XSkpKSkKCmZpdF9zeW1fZ3Vlc3MyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX2d1ZXNzMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX29yaWdpbiwgcGluaV9zY2FsZSwgcGluaV9zY2FsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UpLAogICAgICAgICAgICAgICAgYm9vdHN0cmFwID0gIm5vbmUiKQoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfc3ltX2d1ZXNzMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ndWVzczIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKCiMjIyBTeW0gZ3Vlc3MgdnMgbm8gc3ltIGd1ZXNzCmBgYHtyfQpzeW1fdHdvX2d1ZXNzX3ZzX3N5bV9ndWVzczIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX3R3b19ndWVzczIkbG9nbGlrcywgCiAgZml0X3N5bV9ndWVzczIkbG9nbGlrcykgCgpzeW1fdHdvX2d1ZXNzX3ZzX3N5bV9ndWVzczIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX3R3b19ndWVzczIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKYmVzdF9zeW1fZ3Vlc3MyIDwtIGJlc3Rfc3ltX3R3b19ndWVzczIKYGBgCgoKIyMjIFN5bSBzYW1lIGd1ZXNzCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9zYW1lX2d1ZXNzMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbNV0gKyAoMSAtIDIgKiBwWzVdKSAqIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKSwgCiAgICBmdW5jdGlvbih4LCBwKSBwWzVdICsgKDEgLSAyICogcFs1XSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFs0XSkpKSkKCmZpdF9zeW1fc2FtZV9ndWVzczIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsICByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX3NhbWVfZ3Vlc3MyLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW4sIHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzczIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzczIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIFNhbWUgZ3Vlc3MgdnMgbm8gc2FtZSBzbG9wZQpgYGB7cn0Kc3ltX3NhbWVfZ3Vlc3NfdnNfbm9fc2FtZV9ndWVzczIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3MyJGxvZ2xpa3MpIAoKc3ltX3NhbWVfZ3Vlc3NfdnNfbm9fc2FtZV9ndWVzczIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2d1ZXNzMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgpiZXN0X3N5bV9ub19zYW1lX2d1ZXNzMiA8LSBzeW1fc2FtZV9ndWVzc192c19ub19zYW1lX2d1ZXNzMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2d1ZXNzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spCgpiZXN0X3N5bV9zYW1lX2d1ZXNzMiA8LSBzeW1fc2FtZV9ndWVzc192c19ub19zYW1lX2d1ZXNzMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2d1ZXNzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKQoKYGBgCgojIyMgTm8gc2FtZSBndWVzcyBzYW1lIHNsb3BlCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9ndWVzc19zYW1lX3Nsb3BlMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbNF0gKyAoMSAtIDIgKiBwWzRdKSAqIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKSwgCiAgICBmdW5jdGlvbih4LCBwKSBwWzVdICsgKDEgLSAyICogcFs1XSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkpKSkKCmZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZTIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZTIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9vcmlnaW4sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgoKIyMjIE5vIHNhbWUgZ3Vlc3MgdnMgbm8gc2FtZSBndWVzcyBzYW1lIHNsb3BlCmBgYHtyfQpzeW1fc2FtZV9ndWVzc192c19zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9ndWVzczIkbG9nbGlrcywgCiAgZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRsb2dsaWtzKSAKCnN5bV9zYW1lX2d1ZXNzX3ZzX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3NhbWVfZ3Vlc3MyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCiMjIyBBZGQgdG8gcyB2cyBkCmJlc3Rfc3ltX25vX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIgPC0gYmVzdF9zeW1fbm9fc2FtZV9ndWVzczIKICAKYGBgCgojIyMgQWJzZW50IGxhcHNlcwpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fYWJzZW50X2xhcHNlczIgPC0gIGRhdDIgJT4lIAogIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCBwWzFdICsgcFsyXSwgcFszXSksIAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgcFsxXSAtIHBbMl0sIHBbNF0pKSkpCgpmaXRfc3ltX2Fic2VudF9sYXBzZXMyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX2Fic2VudF9sYXBzZXMyLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW4sIHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgQWJzZW50IGxhcHNlcyB2cyBubyBhYnNlbnQgbGFwc2VzCmBgYHtyfQpzeW1fYWJzZW50X2xhcHNlc192c19ub19hYnNlbnRfbGFwc2VzMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fc2FtZV9ndWVzczIkbG9nbGlrcywgCiAgZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRsb2dsaWtzKSAKCnN5bV9hYnNlbnRfbGFwc2VzX3ZzX25vX2Fic2VudF9sYXBzZXMyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9zYW1lX2d1ZXNzMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgpiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzMiA8LSBzeW1fYWJzZW50X2xhcHNlc192c19ub19hYnNlbnRfbGFwc2VzMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX3NhbWVfZ3Vlc3MyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCmJlc3Rfc3ltX2Fic2VudF9sYXBzZXMyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3ZzX25vX2Fic2VudF9sYXBzZXMyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fc2FtZV9ndWVzczIpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCmBgYAoKIyMjIFN5bSBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFs0XSArICgxIC0gMiAqIHBbNF0pICogcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbM10pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbNF0gKyAoMSAtIDIgKiBwWzRdKSAqIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSkpKQoKZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9vcmlnaW4sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIE5vIGFic2VudCBsYXBzZXMgdnMgbm8gYWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlCmBgYHtyfQpzeW1fbm9fYWJzZW50X2xhcHNlc192c19ub19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9zYW1lX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIkbG9nbGlrcykgCgpzeW1fbm9fYWJzZW50X2xhcHNlc192c19ub19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyIDwtIHN5bV9ub19hYnNlbnRfbGFwc2VzX3ZzX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyIDwtIHN5bV9ub19hYnNlbnRfbGFwc2VzX3ZzX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKQoKYGBgCgojIyMgQWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlIApgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIDAuMDEgKyAoMSAtIDIgKiAwLjAxKSAqIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKSwgCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkpKSkKCmZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMiA8LSBxdWlja3BzeShkYXQyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uLCByZXNwb25zZSwgCiAgICAgICAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlcywgY29uZF9wZXJfYmxvY2spLAogICAgICAgICAgICAgICAgZnVuID0gZnVuX3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW4sIHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIEFic2VudCBsYXBzZXMgdnMgYWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlCmBgYHtyfQpzeW1fYWJzZW50X2xhcHNlc192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRsb2dsaWtzLCAKICBmaXRfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIkbG9nbGlrcykgCgpzeW1fYWJzZW50X2xhcHNlc192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3ZzX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3ZzX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKQoKYGBgCgoKIyMjIEF2ZXJhZ2VzLCBjdXJ2ZXMgYW5kIHBhcmFtZXRlcnMgKGNoZWNraW5nKQpgYGB7cn0Kc3ltX2F2ZXJhZ2VzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIkYXZlcmFnZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIpKQoKc3ltX2N1cnZlc19zX3ZzX2RfdGVzdDIgPC0gCiAgKGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMikpCgoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBzeW1fYXZlcmFnZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKYGBge3J9CnN5bV9hdmVyYWdlc19zX3ZzX2RfdGVzdDIgPC0gCiAgKGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZTIkYXZlcmFnZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub19zYW1lX2d1ZXNzMikpCgpzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRjdXJ2ZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub19zYW1lX2d1ZXNzMikpCgoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaykgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN5bV9hdmVyYWdlc19zX3ZzX2RfdGVzdDIsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IHN5bV9jdXJ2ZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgpgYGB7cn0Kc3ltX2F2ZXJhZ2VzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9zYW1lX2d1ZXNzMiRhdmVyYWdlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpKQoKc3ltX2N1cnZlc19zX3ZzX2RfdGVzdDIgPC0gCiAgKGZpdF9zeW1fc2FtZV9ndWVzczIkY3VydmVzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlMikpCgoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaykgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN5bV9hdmVyYWdlc19zX3ZzX2RfdGVzdDIsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IHN5bV9jdXJ2ZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgpgYGB7cn0Kc3ltX2F2ZXJhZ2VzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMikpCgpzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpKQoKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2spICsKICBnZW9tX3BvaW50KGRhdGEgPSBzeW1fYXZlcmFnZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKYGBge3J9CnN5bV9hdmVyYWdlc19zX3ZzX2RfdGVzdDIgPC0gCiAgKGZpdF9zeW1fYWJzZW50X2xhcHNlczIkYXZlcmFnZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSkKCnN5bV9jdXJ2ZXNfc192c19kX3Rlc3QyIDwtIAogIChmaXRfc3ltX2Fic2VudF9sYXBzZXMyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpKQoKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2spICsKICBnZW9tX3BvaW50KGRhdGEgPSBzeW1fYXZlcmFnZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKYGBge3IgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0Kc3ltX2F2ZXJhZ2VzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMikpCgpzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiA8LSAKICAoZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpKQoKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2spICsKICBnZW9tX3BvaW50KGRhdGEgPSBzeW1fYXZlcmFnZXNfc192c19kX3Rlc3QyLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBzeW1fY3VydmVzX3NfdnNfZF90ZXN0MiwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIEF2ZXJhZ2VzLCBjdXJ2ZXMgYW5kIHBhcmFtZXRlcnMgCmBgYHtyIGZpZy5oZWlnaHQ9MTUsIGZpZy53aWR0aD0xNX0Kc3ltX2F2ZXJhZ2VzX3NfdnNfZDIgPC0gCiAgKGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRhdmVyYWdlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3NhbWVfZ3Vlc3MyKSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9zeW1fc2FtZV9ndWVzczIkYXZlcmFnZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlMiRhdmVyYWdlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRhdmVyYWdlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGF2ZXJhZ2VzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMikpKQoKc3ltX2N1cnZlc19zX3ZzX2QyIDwtIAogIChmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiRjdXJ2ZXMgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIpKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGUyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3NhbWVfZ3Vlc3MyKSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9zeW1fc2FtZV9ndWVzczIkY3VydmVzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlMikpKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIkY3VydmVzICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMikpKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfc3ltX2Fic2VudF9sYXBzZXMyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGN1cnZlcyAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpKSkKCnN5bV9wYXJfc192c19kMiA8LSAKICAoZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIkcGFyICU+JSBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlMiRwYXIgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9ub19zYW1lX2d1ZXNzMikpKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfc3ltX3NhbWVfZ3Vlc3MyJHBhciAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGUyJHBhciAlPiUgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X3N5bV9hYnNlbnRfbGFwc2VzMiRwYXIgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMiRwYXIgJT4lIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyKSkpCgoKc3ltX3Bhcl9zX3ZzX2RfbG9uZzIgPC0gc3ltX3Bhcl9zX3ZzX2QyICU+JSAKICBzcHJlYWQocGFybiwgcGFyKSAKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2spICsKICBnZW9tX3BvaW50KGRhdGEgPSBzeW1fYXZlcmFnZXNfc192c19kMiwgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gc3ltX2N1cnZlc19zX3ZzX2QyLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fdmxpbmUoZGF0YSA9IHN5bV9wYXJfc192c19kX2xvbmcyLAogICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gcDEsIGx0eSA9ICJwMSIpKSArCiAgICBnZW9tX3ZsaW5lKGRhdGEgPSBzeW1fcGFyX3NfdnNfZF9sb25nMiwgCiAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBwMSArIHAyLCBsdHkgPSAicDEgK3AyIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIE5vIHR3byBndWVzcyBzYW1lIHNsb3BlIHplcm8KYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpmdW5fc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3plcm8yIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFsyXSArICsgKDEgLSBwWzJdIC0gcFszXSkgKiBwbm9ybSh4LCAwLCBwWzFdKSwgCiAgICBmdW5jdGlvbih4LCBwKSBwWzRdICsgKDEgLSBwWzRdIC0gcFs1XSkgKiBwbm9ybSh4LCAwLCBwWzFdKSkpKQoKZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiA8LSBxdWlja3BzeShkYXQyLCBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSwgcGluaV9sYXBzZSwgcGluaV9sYXBzZSwgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgTm8gdHdvIGd1ZXNzIHNhbWUgc2xvcGUgemVybyB2cyBubyB0d28gZ3Vlc3Mgc2FtZSBzbG9wZQpgYGB7cn0Kc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3ZzX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3plcm8yIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIkbG9nbGlrcywgCiAgZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiRsb2dsaWtzKSAKCnN5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV92c19ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiAlPiUKICBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yIDwtIHN5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV92c19ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiA8LSBzeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfdnNfbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZTIpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgJT4lIAogIG11dGF0ZShiZXN0ID0gInplcm8iKQoKYGBgCgojIyMgTm8gdHdvIGd1ZXNzIHNhbWUgc2xvcGUgcyAgCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyArICgxIC0gcFszXSAtIHBbNF0pICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFs1XSArICgxIC0gcFs1XSAtIHBbNl0pICogcG5vcm0oeCwgcFsxXSwgcFsyXSkpKSkKCmZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfczIgPC0gcXVpY2twc3koZGF0Miwgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3MyLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW4sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBObyB0d28gZ3Vlc3Mgc2FtZSBzbG9wZSB2cyBubyB0d28gZ3Vlc3Mgc2FtZSBzbG9wZSBzCmBgYHtyfQpzeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfdnNfbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfczIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlMiRsb2dsaWtzLCAKICBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3MyJGxvZ2xpa3MpIAoKc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3ZzX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3MyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCmBgYAoKIyMjIE5vIHR3byBndWVzcyBzYW1lIHNsb3BlIGQgIApgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfZDIgPC0gIGRhdDIgJT4lIAogIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoCiAgICBmdW5jdGlvbih4LCBwKSBwWzNdICsgKyAoMSAtIHBbM10gLSBwWzRdKSAqIHBub3JtKHgsIHBbMV0sIHBbMl0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbNV0gKyAoMSAtIHBbNV0gLSBwWzZdKSAqIHBub3JtKHgsIC1wWzFdLCBwWzJdKSkpKQoKZml0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9kMiA8LSBxdWlja3BzeShkYXQyLCBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfZDIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9zY2FsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UsIHBpbmlfbGFwc2UpLAogICAgICAgICAgICAgICAgYm9vdHN0cmFwID0gIm5vbmUiKQoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX2QyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX2QyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIE5vIHR3byBndWVzcyBzYW1lIHNsb3BlIHZzIG5vIHR3byBndWVzcyBzYW1lIHNsb3BlIGQKYGBge3J9CnN5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV92c19ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV9kMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGUyJGxvZ2xpa3MsIAogIGZpdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfZDIkbG9nbGlrcykgCgpzeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfdnNfbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfZDIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCiMjIyBBZGQgdG8gcyB2cyBkCmJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZnVsbDIgPC0gc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX3ZzX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX2QyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fdHdvX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVybzIpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAiZnVsbCIpCgpgYGAKCiMjIyBObyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgemVybwpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbMl0gKyAoMSAtIDIgKiBwWzJdKSAqIHBub3JtKHgsIDAsIHBbMV0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIDAsIHBbMV0pKSkpCgpmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlLCBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIE5vIHNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSB2cyBubyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgemVybwpgYGB7cn0Kc3ltX2d1ZXNzX3NhbWVfc2xvcGVfdnNfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGUyJGxvZ2xpa3MsIAogIGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiRsb2dsaWtzKSAKCnN5bV9ndWVzc19zYW1lX3Nsb3BlX3ZzX3N5bV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9ub19zYW1lX2d1ZXNzMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgpiZXN0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yIDwtIHN5bV9ndWVzc19zYW1lX3Nsb3BlX3ZzX3N5bV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fc2FtZV9ndWVzczIpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAKCgpgYGAKCiMjIyBObyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgcwpgYGB7ciBmaWcuaGVpZ2h0PTE4LCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIHBbMV0sIHBbMl0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbNF0gKyAoMSAtIDIgKiBwWzRdKSAqIHBub3JtKHgsIHBbMV0sIHBbMl0pKSkpCgpmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfczIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSwgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9zMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX3MyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBObyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyB2cyBubyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyBzCmBgYHtyfQpzeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZTIkbG9nbGlrcywgCiAgZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX3MyJGxvZ2xpa3MpIAoKc3ltX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fczIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVybzIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX25vX3MyIDwtIHN5bV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spIAoKYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyIDwtIHN5bV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAKCmBgYAoKIyMjIE5vIHNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSBkCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9ndWVzc19zYW1lX3Nsb3BlX2QyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFszXSArICgxIC0gMiAqIHBbM10pICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFs0XSArICgxIC0gMiAqIHBbNF0pICogcG5vcm0oeCwgLXBbMV0sIHBbMl0pKSkpCgpmaXRfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfZDIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9kMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSwgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9kMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX2QyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBObyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyB2cyBubyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyfQpzeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZTIkbG9nbGlrcywgCiAgZml0X3N5bV9ndWVzc19zYW1lX3Nsb3BlX2QyJGxvZ2xpa3MpIAoKc3ltX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZDIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVybzIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2Z1bGwyIDwtIHN5bV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2QyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spICU+JSAKICBtdXRhdGUoYmVzdCA9ICJmdWxsIikKCmBgYAoKIyMjIFN5bSBzYW1lIGd1ZXNzIG5vIHNhbWUgc2xvcGUgemVybwpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fc2FtZV9ndWVzc196ZXJvMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIDAsIHBbMV0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIDAsIHBbMl0pKSkpCgpmaXRfc3ltX3NhbWVfZ3Vlc3NfemVybzIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fc2FtZV9ndWVzc196ZXJvMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfc2NhbGUsIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9zYW1lX2d1ZXNzX3plcm8yJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3NfemVybzIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIFNhbWUgZ3Vlc3Mgbm8gc2FtZSBzbG9wZSBubyB6ZXJvIHZzIFNhbWUgZ3Vlc3Mgbm8gc2FtZSBzbG9wZSB6ZXJvCmBgYHtyfQpzeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX3plcm8yIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9zYW1lX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3NfemVybzIkbG9nbGlrcykgCgpzeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX3plcm8yICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV9ub196ZXJvIDwtIHN5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfemVybzIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCiMjIyBBZGQgdG8gcyB2cyBkCmJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV96ZXJvMiA8LSBzeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX3plcm8yICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fbm9fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAiemVybyIpCgpgYGAKCiMjIyBTeW0gc2FtZSBndWVzcyBubyBzYW1lIHNsb3BlIG5vIHplcm8gcwpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fc2FtZV9ndWVzc19ub196ZXJvX3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFs0XSArICgxIC0gMiAqIHBbNF0pICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFs0XSArICgxIC0gMiAqIHBbNF0pICogcG5vcm0oeCwgcFsxXSwgcFszXSkpKSkKCmZpdF9zeW1fc2FtZV9ndWVzc19ub196ZXJvX3MyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX3NhbWVfZ3Vlc3Nfbm9femVyb19zMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzc19ub196ZXJvX3MyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3Nfbm9femVyb19zMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgoKIyMjIFNhbWUgZ3Vlc3Mgbm8gc2FtZSBzbG9wZSBubyB6ZXJvIHZzIFNhbWUgZ3Vlc3Mgbm8gc2FtZSBzbG9wZSBubyB6ZXJvIHMKYGBge3J9CnN5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fc2FtZV9ndWVzczIkbG9nbGlrcywgCiAgZml0X3N5bV9zYW1lX2d1ZXNzX25vX3plcm9fczIkbG9nbGlrcykgCgpzeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fczIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV9ub196ZXJvKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmBgYAoKIyMjIFN5bSBzYW1lIGd1ZXNzIG5vIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9zYW1lX2d1ZXNzX25vX3plcm9fZDIgPC0gIGRhdDIgJT4lIAogIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoCiAgICBmdW5jdGlvbih4LCBwKSBwWzRdICsgKDEgLSAyICogcFs0XSkgKiBwbm9ybSh4LCBwWzFdLCBwWzJdKSwgCiAgICBmdW5jdGlvbih4LCBwKSBwWzRdICsgKDEgLSAyICogcFs0XSkgKiBwbm9ybSh4LCAtcFsxXSwgcFszXSkpKSkKCmZpdF9zeW1fc2FtZV9ndWVzc19ub196ZXJvX2QyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX3NhbWVfZ3Vlc3Nfbm9femVyb19kMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzc19ub196ZXJvX2QyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3Nfbm9femVyb19kMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgU2FtZSBndWVzcyBubyBzYW1lIHNsb3BlIG5vIHplcm8gdnMgU2FtZSBndWVzcyBubyBzYW1lIHNsb3BlIG5vIHplcm8gZApgYGB7cn0Kc3ltX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3ZzX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2QyIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9zYW1lX2d1ZXNzMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3Nfbm9femVyb19kMiRsb2dsaWtzKSAKCnN5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb19kMiU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVybykgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X3N5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBzeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fZDIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9zYW1lX2d1ZXNzX25vX3NhbWVfc2xvcGVfbm9femVybykgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spICU+JSAgCiAgbXV0YXRlKGJlc3QgPSAic2Vuc29yeSIpCgoKYGBgCgojIyMgU3ltIHNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSB6ZXJvIApgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFsyXSArICgxIC0gMiAqIHBbMl0pICogcG5vcm0oeCwgMCwgcFsxXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFsyXSArICgxIC0gMiAqIHBbMl0pICogcG5vcm0oeCwgMCwgcFsxXSkpKSkKCmZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5pX2xhcHNlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX3plcm8yJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBTYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyB2cyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgemVybwpgYGB7cn0Kc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiRsb2dsaWtzKSAKCnN5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX25vX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yIDwtIHN5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfemVybzIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9ub19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgCgoKYGBgCgojIyMgU3ltIHNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSBubyB6ZXJvIHMKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpmdW5fc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgcFszXSArICgxIC0gMiAqIHBbM10pICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgcFszXSArICgxIC0gMiAqIHBbM10pICogcG5vcm0oeCwgcFsxXSwgcFsyXSkpKSkKCmZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fczIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9zY2FsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpbmlfbGFwc2UpLAogICAgICAgICAgICAgICAgYm9vdHN0cmFwID0gIm5vbmUiKQoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBTYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyB2cyBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyBzCmBgYHtyfQpzeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZTIkbG9nbGlrcywgCiAgZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19zMiRsb2dsaWtzKSAKCnN5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19zMiAlPiUKICBzZW1pX2pvaW4oYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmBgYAoKIyMjIFN5bSBzYW1lIGd1ZXNzIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIHBbMV0sIHBbMl0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIHBbM10gKyAoMSAtIDIgKiBwWzNdKSAqIHBub3JtKHgsIC1wWzFdLCBwWzJdKSkpKQoKZml0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSBxdWlja3BzeShkYXQyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uLCByZXNwb25zZSwgCiAgICAgICAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlcywgY29uZF9wZXJfYmxvY2spLAogICAgICAgICAgICAgICAgZnVuID0gZnVuX3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19kMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluaV9sYXBzZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZDIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZDIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIFNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSBubyB6ZXJvIHZzIHNhbWUgZ3Vlc3Mgc2FtZSBzbG9wZSBubyB6ZXJvIGQKYGBge3J9CnN5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb192c19zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlMiRsb2dsaWtzLCAKICBmaXRfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2QyJGxvZ2xpa3MpIAoKc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2QyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9zYW1lX2d1ZXNzX3NhbWVfc2xvcGVfbm9femVybzIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZnVsbDIgPC0gc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgJT4lIAogIG11dGF0ZShiZXN0ID0gImZ1bGwiKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fc2FtZV9ndWVzc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gInNlY29uZCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spICU+JSAKICBtdXRhdGUoYmVzdCA9ICJzZW5zb3J5IikKCmBgYAoKIyMjIEFic2VudCBsYXBzZXMgbm8gc2FtZSBzbG9wZSB6ZXJvIApgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3plcm8yIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgMCwgcFsxXSksIAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgMCwgcFsyXSkpKSkKCmZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3plcm8yIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV96ZXJvMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfc2NhbGUsIHBpbmlfc2NhbGUpLAogICAgICAgICAgICAgICAgYm9vdHN0cmFwID0gIm5vbmUiKQoKZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiBjb25kX3Blcl9ibG9jaywgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV96ZXJvMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfemVybzIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIEFic2VudCBsYXBzZXMgbm8gc2FtZSBzbG9wZSAgIHZzIGFic2VudCBsYXBzZXMgbm8gc2FtZSBzbG9wZSB6ZXJvIApgYGB7cn0Kc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV92c19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfemVybzIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2Fic2VudF9sYXBzZXMyJGxvZ2xpa3MsIAogIGZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3plcm8yJGxvZ2xpa3MpIAoKc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV92c19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfemVybzIgJT4lCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKQoKYGBgCgojIyMgQWJzZW50IGxhcHNlcyBubyBzYW1lIHNsb3BlIG5vIHplcm8gcwpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZ1bl9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgcFsxXSwgcFszXSkpKSkKCmZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3MyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9zMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfczIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3MyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBBYnNlbnQgbGFwc2VzIG5vIHNhbWUgc2xvcGUgbm8gemVybyB2cyBhYnNlbnQgbGFwc2VzIG5vIHNhbWUgc2xvcGUgbm8gemVybyBzCmBgYHtyfQpzeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2Fic2VudF9sYXBzZXMyJGxvZ2xpa3MsIAogIGZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX3MyJGxvZ2xpa3MpIAoKc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX25vX3MyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfbm9femVyb19zMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAic2Vuc29yeSIpCgpgYGAKCiMjIyBBYnNlbnQgbGFwc2VzIG5vIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfZDIgPC0gIGRhdDIgJT4lIAogIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCBwWzFdLCBwWzJdKSwgCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCAtcFsxXSwgcFszXSkpKSkKCmZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX2QyIDwtIHF1aWNrcHN5KGRhdDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2VzLCBjb25kX3Blcl9ibG9jayksCiAgICAgICAgICAgICAgICBmdW4gPSBmdW5fc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9kMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfZDIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX2QyJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcywgbHR5ID0gImFsbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBBYnNlbnQgbGFwc2VzIG5vIHNhbWUgc2xvcGUgbm8gemVybyB2cyBhYnNlbnQgbGFwc2VzIG5vIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyfQpzeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fZDIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2Fic2VudF9sYXBzZXMyJGxvZ2xpa3MsIAogIGZpdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX2QyJGxvZ2xpa3MpIAoKc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2QyICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGUyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCiMjIyBBZGQgdG8gcyB2cyBkCmJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2Z1bGwyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX25vX3NhbWVfc2xvcGVfbm9femVyb19kMiAlPiUgCiAgc2VtaV9qb2luKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZTIpICU+JSAKICBhbnRpX2pvaW4oYmVzdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fczIsIGJ5ID0gYygic3ViamVjdCIsICJjb25kX3Blcl9ibG9jayIpKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgJT4lIAogIG11dGF0ZShiZXN0ID0gImZ1bGwiKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlX25vX3plcm9fZDIgPC0gc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2QyICU+JSAKICBzZW1pX2pvaW4oYmVzdF9zeW1fYWJzZW50X2xhcHNlc19ub19zYW1lX3Nsb3BlMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAiZGVjaXNpb24iKQoKYGBgCgoKIyMjIEFic2VudCBsYXBzZXMgc2FtZSBzbG9wZSB6ZXJvCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIgPC0gIGRhdDIgJT4lIAogIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCAwLCBwWzFdKSwgCiAgICBmdW5jdGlvbih4LCBwKSAwLjAxICsgKDEgLSAyICogMC4wMSkgKiBwbm9ybSh4LCAwLCBwWzFdKSkpKQoKZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX3plcm8yLAogICAgICAgICAgICAgICAgeG1pbiA9IC0zLCB4bWF4ID0gMywKICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9zY2FsZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX3plcm8yJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV96ZXJvMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgQWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlIG5vIHplcm8gdnMgYWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlIHplcm8KYGBge3J9CnN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIgPC0gbW9kZWxfc2VsZWN0aW9uX2xydCgKICBmaXRfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZTIkbG9nbGlrcywgCiAgZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIkbG9nbGlrcykgCgpzeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX3plcm8yICU+JQogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCmJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm8yIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykKCiMjIyBBZGQgdG8gcyB2cyBkCmJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX3plcm8yIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfemVybzIgJT4lIAogIHNlbWlfam9pbihiZXN0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gInNlY29uZCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2spICU+JSAKICBtdXRhdGUoYmVzdCA9ICJ6ZXJvIikKCmBgYAoKIyMjIEFic2VudCBsYXBzZXMgc2FtZSBzbG9wZSBubyB6ZXJvIHMKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTE1fQpmdW5fc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX3MyIDwtICBkYXQyICU+JSAKICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgcFsxXSwgcFsyXSksIAogICAgZnVuY3Rpb24oeCwgcCkgMC4wMSArICgxIC0gMiAqIDAuMDEpICogcG5vcm0oeCwgcFsxXSwgcFsyXSkpKSkKCmZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIgPC0gcXVpY2twc3koZGF0MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgZ3JvdXBpbmcgPSAuKHN1YmplY3QsIHJlZmVyZW5jZXMsIGNvbmRfcGVyX2Jsb2NrKSwKICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIsCiAgICAgICAgICAgICAgICB4bWluID0gLTMsIHhtYXggPSAzLAogICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbiwgcGluaV9zY2FsZSksCiAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IGNvbmRfcGVyX2Jsb2NrLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIkYXZlcmFnZXMsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzLCBsdHkgPSAiYWxsIikpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIEFic2VudCBsYXBzZXMgc2FtZSBzbG9wZSBubyB6ZXJvIHZzIGFic2VudCBsYXBzZXMgc2FtZSBzbG9wZSBubyB6ZXJvIHMKYGBge3J9CnN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlMiRsb2dsaWtzLCAKICBmaXRfc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX3MyJGxvZ2xpa3MpIAoKc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX3MyICU+JQogIHNlbWlfam9pbihiZXN0X2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpCgpiZXN0X2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX25vX3MyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMiAlPiUgCiAgc2VtaV9qb2luKGJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgCgoKYmVzdF9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBzeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIgJT4lIAogIHNlbWlfam9pbihiZXN0X2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAKCgpgYGAKCiMjIyBBYnNlbnQgbGFwc2VzIHNhbWUgc2xvcGUgbm8gemVybyBkCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZnVuX3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSAgZGF0MiAlPiUgCiAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogIGJpbmRfY29scyh0aWJibGUoZnVuID0gYygKICAgIGZ1bmN0aW9uKHgsIHApIDAuMDEgKyAoMSAtIDIgKiAwLjAxKSAqIHBub3JtKHgsIHBbMV0sIHBbMl0pLCAKICAgIGZ1bmN0aW9uKHgsIHApIDAuMDEgKyAoMSAtIDIgKiAwLjAxKSAqIHBub3JtKHgsIC1wWzFdLCBwWzJdKSkpKQoKZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19kMiA8LSBxdWlja3BzeShkYXQyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uLCByZXNwb25zZSwgCiAgICAgICAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlcywgY29uZF9wZXJfYmxvY2spLAogICAgICAgICAgICAgICAgZnVuID0gZnVuX3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19kMiwKICAgICAgICAgICAgICAgIHhtaW4gPSAtMywgeG1heCA9IDMsCiAgICAgICAgICAgICAgICBwYXJpbmkgPSBsaXN0KHBpbmlfb3JpZ2luLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gY29uZF9wZXJfYmxvY2ssIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19kMiRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19kMiRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMsIGx0eSA9ICJhbGwiKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgojIyMgQWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlIG5vIHplcm8gdnMgYWJzZW50IGxhcHNlcyBzYW1lIHNsb3BlIG5vIHplcm8gZApgYGB7cn0Kc3ltX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX3ZzX2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX2QyIDwtIG1vZGVsX3NlbGVjdGlvbl9scnQoCiAgZml0X3N5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGUyJGxvZ2xpa3MsIAogIGZpdF9zeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fZDIkbG9nbGlrcykgCgpzeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fZDIgJT4lCiAgc2VtaV9qb2luKGJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkKCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvX25vX3MyIDwtIHN5bV9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb192c19hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMiAlPiUgCiAgc2VtaV9qb2luKGJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm8yKSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCBjb25kX3Blcl9ibG9jaykgJT4lIAogIG11dGF0ZShiZXN0ID0gImZ1bGwiKQoKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMiA8LSBzeW1fYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fdnNfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fczIgJT4lIAogIHNlbWlfam9pbihiZXN0X2Fic2VudF9sYXBzZXNfc2FtZV9zbG9wZV9ub196ZXJvMikgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIGNvbmRfcGVyX2Jsb2NrKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAic2Vuc29yeSIpCgoKCmBgYAoKCiMjIyMgQWRkIGFsbCBiZXN0CmBgYHtyfQpiZXN0MiA8LSBiZXN0X3N5bV9ub190d29fZ3Vlc3Nfc2FtZV9zbG9wZV96ZXJvMiAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX25vX3R3b19ndWVzc19zYW1lX3Nsb3BlX25vX3plcm9fZnVsbDIpICU+JSAKICBiaW5kX3Jvd3MoYmVzdF9zeW1fZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2Z1bGwyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfbm9fc2FtZV9zbG9wZV96ZXJvMikgJT4lICAKICBiaW5kX3Jvd3MoYmVzdF9zeW1fc2FtZV9ndWVzc19ub19zYW1lX3Nsb3BlX25vX3plcm9fczIpICU+JSAgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX2Z1bGwyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX3NhbWVfZ3Vlc3Nfc2FtZV9zbG9wZV9ub196ZXJvX3MyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX3MyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2Z1bGwyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3Rfc3ltX2Fic2VudF9sYXBzZXNfbm9fc2FtZV9zbG9wZV9ub196ZXJvX2QyKSAlPiUgCiAgYmluZF9yb3dzKGJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX3plcm8yKSAlPiUgCiAgYmluZF9yb3dzKGJlc3RfYWJzZW50X2xhcHNlc19zYW1lX3Nsb3BlX25vX3plcm9fbm9fczIpICU+JSAKICBiaW5kX3Jvd3MoYmVzdF9hYnNlbnRfbGFwc2VzX3NhbWVfc2xvcGVfbm9femVyb19zMikgCgoKCgoKc3ltX2F2ZXJhZ2VzX3NfdnNfZF9iZXN0MiA8LSAgc3ltX2F2ZXJhZ2VzX3NfdnNfZDIgJT4lCiAgbGVmdF9qb2luKGJlc3QyKSAKICAKc3ltX2N1cnZlc19zX3ZzX2RfYmVzdDIgPC0gc3ltX2N1cnZlc19zX3ZzX2QyICU+JSAKICBsZWZ0X2pvaW4oYmVzdDIpCgpzeW1fcGFyX3NfdnNfZF9iZXN0MiA8LSBzeW1fcGFyX3NfdnNfZDIgJT4lIAogIGxlZnRfam9pbihiZXN0MikgCgpzeW1fcGFyX3NfdnNfZF9iZXN0X2xvbmcyIDwtIHN5bV9wYXJfc192c19kX2Jlc3QyICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgY29uZF9wZXJfYmxvY2ssIHBhciwgYmVzdCwgcGFybikgJT4lIAogIHNwcmVhZChwYXJuLCBwYXIpIAoKc3ltX3Bhcl9zX3ZzX2RfYmVzdF9hYnMyIDwtIHN5bV9wYXJfc192c19kX2Jlc3QyICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIocGFybiA9PSAicDEiIHwgcGFybiA9PSAicDIiKSAlPiUgCiAgICAgICAgICAgICAgbXV0YXRlKHBhcm4gPSBpZl9lbHNlKHBhcm4gPT0gInAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlbnNvcnlcbmJpYXMiLCAiRGVjaXNpb25hbFxuYmlhcyIpLAogICAgICAgICAgICAgICAgICAgICBhYnNfcGFyID0gYWJzKHBhcikpCgpgYGAKCiMjIyBTYXZlIGRhdGEKYGBge3J9CnNhdmUoc3ltX2F2ZXJhZ2VzX3NfdnNfZF9iZXN0LCBmaWxlID0gImxvZ2RhdGEvc3ltX2F2ZXJhZ2VzX3NfdnNfZF9iZXN0Mi5SZGF0YSIpCnNhdmUoc3ltX2N1cnZlc19zX3ZzX2RfYmVzdCwgZmlsZSA9ICJsb2dkYXRhL3N5bV9jdXJ2ZXNfc192c19kX2Jlc3QyLlJEYXRhIikKc2F2ZShzeW1fcGFyX3NfdnNfZF9iZXN0LCBmaWxlID0gImxvZ2RhdGEvc3ltX3Bhcl9zX3ZzX2RfYmVzdF9sb25nMi5SRGF0YSIpCnNhdmUoc3ltX3Bhcl9zX3ZzX2RfYmVzdF9sb25nLCBmaWxlID0gImxvZ2RhdGEvc3ltX3Bhcl9zX3ZzX2RfYmVzdF9hYnMyLlJEYXRhIikKCmBgYAoKCgo=